import logging
from typing import Any, Dict

from fastapi import APIRouter, Depends, Request
from pydantic import BaseModel, EmailStr
from sqlalchemy.ext.asyncio import AsyncSession
from passlib.hash import bcrypt

from app.db import get_db
from app.repositories.user_repository import get_user_by_email
from app.security.jwt import create_access_token
from app.utils.error_handlers import raise_auth_error

logger = logging.getLogger("app.error")

router = APIRouter(prefix="/auth", tags=["auth"])


class LoginRequest(BaseModel):
    email: EmailStr
    password: str


class LoginResponse(BaseModel):
    accessToken: str
    role: str


def _get_request_id(request: Request) -> str:
    """Safely extract request ID from request state"""
    return getattr(request.state, "request_id", "unknown")


@router.post(
    "/login",
    response_model=LoginResponse,
    summary="用户登录",
    description="用户通过邮箱和密码进行登录认证，成功后返回JWT访问令牌",
    openapi_extra={
        "x-roles": ["hr", "interviewer", "boss"],
    },
)
async def login(payload: LoginRequest, request: Request, db: AsyncSession = Depends(get_db)) -> Dict[str, Any]:
    """
    用户登录认证
    
    - **email**: 用户邮箱地址
    - **password**: 用户密码
    
    登录成功后返回：
    - **accessToken**: JWT访问令牌，用于后续API调用
    - **role**: 用户角色(hr/interviewer/boss)
    
    错误情况：
    - 邮箱或密码错误
    - 用户账户被禁用
    """
    request_id = _get_request_id(request)
    
    user = await get_user_by_email(db, payload.email)
    if not user or not user.active:
        logger.warning("login_failed", extra={
            "email": payload.email, 
            "reason": "not_found_or_inactive", 
            "request_id": request_id
        })
        raise_auth_error("invalid_credentials", "email or password is incorrect")

    if not bcrypt.verify(payload.password, user.password_hash):
        logger.warning("login_failed", extra={
            "email": payload.email, 
            "reason": "bad_password", 
            "request_id": request_id
        })
        raise_auth_error("invalid_credentials", "email or password is incorrect")

    token = create_access_token({"sub": user.id, "role": user.role})
    logger.info("login_success", extra={
        "user_id": user.id, 
        "email": user.email, 
        "request_id": request_id
    })
    return {"accessToken": token, "role": user.role} 